using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;

using Sound;
using Input;

using SunXNA.RainbowXNA;
using SunXNA;
using NeedsMoreNinja.EventManager;
using SunXNA.CameraManager;

using MainEngine;

using Darwin.Source.Components.World;

namespace Darwin
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class CGameEngine : Microsoft.Xna.Framework.Game
    {
        private BoundingBox m_worldSize;

        private Darwin.Source.Components.World.World m_World;

        CRainbowXNA.FontHandleType m_fontHandle;

        //CRainbowXNA.TextureObjectHandleType m_failHandle;

#if USE_FPS

        private int FPS = 0;
        private double m_elapsedTime = 0.0f;
        private int m_frameCount = 0;

#endif
        /// <summary>
        /// 
        /// </summary>
        public CGameEngine()
        {
            Content.RootDirectory = "Content";

            m_World = new World();
            //Random test value
            m_worldSize = new BoundingBox(new Vector3(-m_World.Size, -m_World.LowestPoint, -m_World.Size), new Vector3(m_World.Size, m_World.HighestPoint, m_World.Size));

        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            Singleton<SunXNA.RainbowXNA.CRainbowXNA>.Create();
            Singleton<SunXNA.RainbowXNA.CRainbowXNA>.Instance.Create(this, 1280, 720, false, m_worldSize);

#if DEBUG_GRAPHICS_ENABLED
            Singleton<SunXNA.DebugGraphics.CManager>.Create();
#endif

            Singleton<CCameraManager>.Create();

            //MainEngine.MainEngine.getMainEngine(this);
            this.Components.Add(MainEngine.MainEngine.getMainEngine(this));

            base.Initialize();
        }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            SoundManager sm = SoundManager.getSoundManager(this);
            this.Components.Add(sm);
            
            // Load the sounds
            sm.addSound("GameData/Sounds/Menu_Click");  // 0 => Menu click
            sm.addSound("GameData/Sounds/GameOver");  // 1 => GameOver
            sm.addSound("GameData/Sounds/Hit"); // 2 => Minions die
            sm.addSound("GameData/Sounds/Canon"); // 3 => Canon shoots

            m_fontHandle = Singleton<CRainbowXNA>.Instance.CreateFont("GameData/Fonts/DefaultFont");

            base.LoadContent();
        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {

        }

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
#if USE_FPS
            m_elapsedTime += gameTime.ElapsedGameTime.TotalSeconds;
            if (m_elapsedTime > 1.0)
            {
                FPS = m_frameCount;
                m_elapsedTime -= 1.0;
                m_frameCount = 0;
            }
#endif

            // Allows the game to exit
            if (GamePad1.isButtonBackPressedP1())
                this.Exit();

            if (Input.PCKeyboard.isEscapePressed())
                this.Exit();

#if DEBUG_GRAPHICS_ENABLED && false
            Vector3 testPoint = Vector3.Zero;
            Vector3 testNormal = Vector3.Zero;

            //
            //  Given a valid XZ value the terrain will return to you a height at that point, and the normal of the triangle you are on
            //
            testPoint.Y = Singleton<SunXNA.Terrain.CTerrain>.Instance.GetHeightAtXZ(testPoint, out testNormal);

            Singleton<SunXNA.DebugGraphics.CManager>.Instance.Add3DObject(9001,                             //you decide the UID, theres a very good reason for this...
                                                                          SunXNA.DebugGraphics.Type.Box,    //only boxes are available =]
                                                                          Color.Aqua,                       //any color you like
                                                                          testPoint,                        //send in a world position
                                                                          testNormal,                       //this is the direction it will face
                                                                          new Vector3( 0.1f, 0.1f, 5.0f ),  //this is scale, z scale is the scale along the direction... so this code will make it 5 tall... because its pointing up =]
                                                                          1.0f);                            //how long the graphic is alive for, < 0.0f will last FOREVAR!! ^__^
#endif
            base.Update(gameTime);
        }

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
#if USE_FPS
            ++m_frameCount;
#endif


            base.Draw(gameTime);
        }
    }
}
